package com.yanwq.simpleindexview;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Build;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;

import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 作者：闫伟强。
 * 日期：2016/6/2。
 */
public class IndexView extends View {

    private Map<String, Integer> indexMap;
    private Map<Integer, String> posMap;
    private String[] letters;
    private Paint paint;
    private float height;
    private float unitHeight;

    private TextView letterText;

    private OnIndexTouchListener onIndexTouchListener;

    public void setOnIndexTouchListener(OnIndexTouchListener onIndexTouchListener) {
        this.onIndexTouchListener = onIndexTouchListener;
    }

    public IndexView(Context context) {
        super(context);
        init();
    }

    public IndexView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public IndexView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public IndexView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    private void init() {
        indexMap = new HashMap<>();
        posMap = new HashMap<>();
        letters = new String[0];
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setTextSize(14 * getResources().getDisplayMetrics().density);
        addLetterText();
    }

    /**
     * @param indexList The letters list of the index in your data or bean that you want it be.
     *                  从列表数据中提取的索引列表。
     */
    public void initIndex(final List<String> indexList) {
        post(new Runnable() {
            @Override
            public void run() {
                calIndex(indexList);
                IndexView.this.indexMap = indexMap;
                letters = new String[indexMap.size()];
                indexMap.keySet().toArray(letters);
                Arrays.sort(letters, new Comparator<String>() {
                    @Override
                    public int compare(String s, String t1) {

                        if (s.length() > t1.length()) {
                            return 1;
                        }

                        return s.compareTo(t1);
                    }
                });
                height = getMeasuredHeight();
                unitHeight = height / indexMap.size();
                requestLayout();
            }
        });
    }

    private void calIndex(List<String> stringList) {
        String word = null;
        int i = 0;
        for (String s : stringList) {
            String index = String.valueOf(s.charAt(0));

            if (!index.equals(word)) {
                word = index;
                indexMap.put(word, i);
            }

            i++;
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int i = 0;

        for (String letter : letters) {
            Paint.FontMetrics fontMetrics = paint.getFontMetrics();
            float textWidth = paint.measureText(letter, 0, letter.length());
            float x = (getMeasuredWidth() - textWidth) / 2;
            float y = i * unitHeight + (unitHeight - (fontMetrics.bottom - fontMetrics.top)) / 2 - fontMetrics.top;
            canvas.drawText(letter, x, y, paint);
            posMap.put(i, letter);
            i++;
        }
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
                setBackgroundColor(0x44000000);
                float x = event.getX();
                float y = event.getY();
                int pos = (int) (y / unitHeight);

                if (pos > posMap.size() - 1) {
                    return true;
                }

                String letter = posMap.get(pos);
                int index = indexMap.get(letter);

                showLetter(letter);

                if (onIndexTouchListener != null) {
                    onIndexTouchListener.onIndexTouched(letter);
                    onIndexTouchListener.onMappedPosition(index);
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                setBackgroundColor(0x00000000);
                break;
        }

        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return super.onTouchEvent(event);
    }

    private void addLetterText() {
        letterText = new TextView(getContext());
        letterText.setBackgroundResource(R.drawable.bg_letter);
        letterText.setTextColor(0xffffffff);
        letterText.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
        letterText.setGravity(Gravity.CENTER);
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.WRAP_CONTENT,
                FrameLayout.LayoutParams.WRAP_CONTENT);
        params.gravity = Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL;
        if (!isInEditMode()) {
            ((Activity) getContext()).getWindow().addContentView(letterText, params);
        }
        letterText.setVisibility(View.GONE);
    }

    private void showLetter(String letter) {
        removeCallbacks(dismissLetter);
        letterText.setText(letter);
        letterText.setVisibility(View.VISIBLE);
        postDelayed(dismissLetter, 800);
    }

    private Runnable dismissLetter = new Runnable() {
        @Override
        public void run() {
            letterText.setVisibility(View.GONE);
        }
    };

    public interface OnIndexTouchListener {
        void onIndexTouched(String s);

        void onMappedPosition(int position);
    }
}
